package QianFeng07.IODemo2.NIO;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * 通道：Channel
 * Channel是一个对象，可以通过它读取和写入数据。拿NIO与原来的I/O做个比较，通道就像是流。
 * 正如前面提到的，所有数据都通过Buffer对象来处理。您永远不会将字节直接写入通道中，
 * 相反，您是将数据写入包含一个或者多个字节的缓冲区。同样，您不会直接从通道中读取字节，
 * 而是将数据从通道读入缓冲区，再从缓冲区获取这个字节。
 *
 * 比较IO操作的性能：
 * 1、内存映射最块
 * 2、NIO读写文件
 * 3、使用了缓存的IO流
 * 4、无缓存的IO流
 **/
public class CopyFileDemo {

    public static void main(String[] args) {
        try {
            //copyFile();
            randomAccessFileCopy();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //内存映射文件来代替RandomAccessFile 实现文件的复制
    private static void randomAccessFileCopy() throws IOException {
        RandomAccessFile in = new RandomAccessFile("F:\\Test\\my\\1.jpg", "r");
        RandomAccessFile out = new RandomAccessFile("F:\\Test\\my\\4.jpg", "rw");
        //获取通道
        FileChannel fcIn = in.getChannel();
        FileChannel fcOut = out.getChannel();

        /*内存映射*/
        long size = fcIn.size();//输出流的字节大小
        //输入流的缓冲区
        MappedByteBuffer inBuffer = fcIn.map(MapMode.READ_ONLY, 0, size);
        //输出流的缓冲区
        MappedByteBuffer outBuffer = fcOut.map(MapMode.READ_WRITE, 0, size);

        for (int i = 0; i < size; i++) {
            outBuffer.put(inBuffer.get());
        }
        //关闭（关闭通道会写入数据块）
        fcIn.close();
        fcOut.close();
        in.close();
        out.close();
        System.out.println("copy success!");
    }

    //通过文件通道实现文件的复制
    private static void copyFile() throws IOException {
        //创建一个输入（读取）文件的通道
        FileChannel fcIn = new FileInputStream("F:\\Test\\my\\1.jpg").getChannel();
        //创建一个输出（写入）文件的通道
        FileChannel fcOut = new FileOutputStream("F:\\Test\\my\\3.jpg").getChannel();
        //定义缓冲空间大小
        ByteBuffer buf = ByteBuffer.allocate(1024);
        while (fcIn.read(buf) != -1) {
            buf.flip();//确定读取的内容区间 提高读取效率
            fcOut.write(buf);
            buf.clear();
        }
        fcIn.close();
        fcOut.close();
        System.out.println("copy success!");
    }

}
